package cn.majingjing.core.tool;

import cn.majingjing.core.json.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;

/**
 * 系统工具类
 *
 * @author Administrator - JingjingMa
 * @version 3.2
 * @Email <a href="majinding888@163.com">majinding888@163.com</a>
 * @date 2013年3月21日 下午10:02:20
 * @DevTool Created By Eclipse 4.6.2
 */
public class Tools {
    private static Logger log = LoggerFactory.getLogger(Tools.class);

    /**
     * 如果obj为则返回默认默认给定的值
     *
     * @param obj
     * @param defaultObj
     * @param <T>
     * @return
     */
    public static <T> T objectNull2Default(T obj,T defaultObj){
        return Tools.isNull(obj)?defaultObj:obj;
    }

    /**
     * 比较两个简单对象的值是否相等
     *
     * @param a
     * @param b
     * @return
     */
    public static boolean equals(Object a, Object b) {
        if(a instanceof Number && b instanceof Number){
            return Tools.toStrings(a).equals(Tools.toStrings(b));
        }
        return (a == b) || (a != null && a.equals(b));
    }

    /**
     * 判断是否为空(比较对象为null)<br/>
     * (空:true,非空:false)
     *
     * @param obj
     * @return
     */
    public static boolean isNull(Object obj) {
        return (null == obj);
    }

    /**
     * 判断是否非空(比较对象为null)<br/>
     * (不为空:true,空:false)
     *
     * @param obj
     * @return
     */
    public static boolean isNotNull(Object obj) {
        return !isNull(obj);
    }

    /**
     * 判断是否为空(比较对象为null和值)<br/>
     * (空:true,非空:false)<br/>
     * <p>
     * <ul>
     * <li>
     * null ---> true
     * </li>
     * <li>
     * ""  or "&nbsp;"---> true
     * </li>
     * <li>
     * (Integer)0 ---> true
     * </li>
     * <li>
     * (List.size()==0)list ---> true
     * </li>
     * <li>
     * ([])array ---> true
     * </li>
     * </ul>
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null)
            return true;
        if (obj instanceof String) {
            if ("".equals(((String) obj).trim()))
                return true;
        }
        if (obj instanceof Integer) {
            if ((Integer) obj == 0)
                return true;
        }
        if (obj instanceof Collection) {
            Collection c = (Collection) obj;
            return c.isEmpty();
        }
        if (obj.getClass().isArray()) {
            Object[] array = (Object[]) obj;
            return array.length == 0;
        }
        return false;
    }

    /**
     * 判断是否不为空
     *
     * @param obj
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:03:48
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    /**
     * 转换成byte[]类型
     * @param obj
     * @return
     */
    public static byte[] toBytes(String obj) {
        if(null == obj){
            return null;
        }
        try {
            return obj.getBytes("utf-8");
        } catch (Exception e) {
            //e.printStackTrace();
            return null;
        }
    }

    /**
     * 转换成Long类型
     *
     * @param obj
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:04:05
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static Long toLong(Object obj) {
        return Long.valueOf(String.valueOf(obj));
    }

    /**
     * 转换成Integer类型
     *
     * @param obj
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:04:18
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static Integer toInteger(Object obj) {
        return Integer.valueOf(String.valueOf(obj));
    }

    /**
     * 将Object类型转换成String类型,null将转换成""
     *
     * @param obj
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:04:35
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static String toStrings(Object obj) {
        if(null == obj){
            return "";
        }
        if(obj instanceof byte[]){
            try {
                return new String((byte[])obj,"utf-8");
            } catch (Exception e) {
                //e.printStackTrace();
                return "";
            }
        }
        return String.valueOf(obj);
    }

    /**
     * 转换成字符串
     * <p>
     * <pre>
     * toStrings("欢迎：{},现在时间是：{}","皇太极",new Date());
     * 返回结果为：欢迎：皇太极,现在时间是：Tue Mar 21 21:55:44 CST 2017
     * </pre>
     *
     * @param s
     * @param obj
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午9:56:18
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static String toStrings(String s, Object... obj) {
        // try {
        // s = String.format(s.replace("{}", "%s"), obj);
        // } catch (Exception e) {
        // log.error("占位符和参数不匹配?");
        // log.error("{}", e);
        // throw new RuntimeException("占位符和参数不匹配?");
        // }
        // return s;
        StringBuilder sb = new StringBuilder(s);
        for (int i = 0, m = sb.indexOf("{}"); i < obj.length && m > -1; i++, m = sb.indexOf("{}")) {
            sb.delete(m, m + 2).insert(m, obj[i]);
        }
        return sb.toString();
    }

    /**
     * 转义字符串
     *
     * @param message
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:05:44
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static String filterDangerString(String message) {
        if (message == null) {
            return null;
        }
        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
                case '<':
                    result.append("&lt;");
                    break;
                case '>':
                    result.append("&gt;");
                    break;
                case '&':
                    result.append("&amp;");
                    break;
                case '"':
                    result.append("&quot;");
                    break;
                default:
                    result.append(content[i]);
            }
        }
        return result.toString();
    }

    /**
     * UUID字符串
     *
     * @return
     */
    private static String javaUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 返回小写的uuid(36位)
     *
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:08:13
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static String uuid() {
        return javaUUID().toLowerCase();
    }

    /**
     * 返回大写的uuid(36位)
     *
     * @return
     * @author Administrator - JingjingMa
     * @Email <a href="majinding888@163.com">majinding888@163.com</a>
     * @date 2017年3月21日 下午10:10:23
     * @version 3.2
     * @DevTool Created By Eclipse 4.3
     */
    public static String UUID() {
        return javaUUID().toUpperCase();
    }

    @Deprecated
    public static long longUuid() {
        return UUID.randomUUID().getMostSignificantBits();
    }

    /**
     * 返回大写的GUID(32位)
     *
     * @return
     */
    public static String GUID() {
        return UUID().replace("-", "");
    }

    /**
     * 返回小写的guid(32位)
     *
     * @return
     */
    public static String guid() {
        return uuid().replace("-", "");
    }

    /**
     * 根据给定单词获取指定长度的单词
     *
     * @param s
     * @param len
     * @return
     */
    public static String getWords(String s, int len) {
        if (Tools.isNotEmpty(s) && s.length() > len) {
            return s.substring(0, len);
        } else {
            return s;
        }
    }

    /**
     * 根据给定单词和key值获取键的值
     *
     * @param word
     * @param k
     * @return
     */
    public static String getKVWord(String word, Integer k) {
        String[] words = word.split(",");
        Map<String, String> m = new HashMap<>();
        for (String w : words) {
            String[] kv = w.split(":");
            if (null == kv || kv.length == 1) {
                m.put("default", w);
            } else {
                m.put(kv[0], kv[1]);
            }
        }
        if (m.containsKey(toStrings(k))) {
            return m.get(toStrings(k));
        }
        return m.get("default");
    }

    /**
     * @param obj 对象转换成map
     * @return
     * @throws IntrospectionException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @author: Administrator - JingjingMa
     * @Email: <a href="majinding888@163.com">majinding888@163.com</a>
     * @date: 2015-09-06 11:38:45
     */
    public static Map<String, Object> objectToMap(Object obj)
            throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        Map<String, Object> map = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            if (!property.getName().equals("class")) {
                Object realVal = property.getReadMethod().invoke(obj);
                if (realVal != null) {
                    map.put(property.getName(), realVal);
                } else {
                    map.put(property.getName(), "");
                }
            }
        }
        return map;
    }

    private static String hexString = "0123456789ABCDEF";

    /**
     * 将字符串编码成16进制数字,适用于所有字符（包括中文）
     */
    public static String encodeStrTo16(String str) {
        // 根据默认编码获取字节数组
        byte[] bytes = str.getBytes();
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        // 将字节数组中每个字节拆解成2位16进制整数
        for (int i = 0; i < bytes.length; i++) {
            sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
            sb.append(hexString.charAt((bytes[i] & 0x0f)));
        }
        return sb.toString();
    }

    /**
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    public static String decode16ToStr(String bytes) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray());
    }

    /**
     * 打印日志[仅方便单元测试使用]
     *
     * @param obj
     * @return
     */
    public static void printLog(Object obj) {
        System.out.println(">>>>>>>>开始打印日志>>>>>>>>");
        if (obj instanceof String) {
            System.out.println(obj);
        } else {
            System.out.println(JacksonUtil.toJson(obj));
        }
        System.out.println("<<<<<<<<结束打印日志<<<<<<<<");
    }

    /**
     * 驼峰转下划线写法
     *
     * @param name
     * @return
     */
    public static String toUnderscoreName(String name) {
        if (Tools.isEmpty(name)) {
            return "";
        } else {
            StringBuilder result = new StringBuilder();
            result.append(name.substring(0, 1).toLowerCase());

            for (int i = 1; i < name.length(); ++i) {
                String s = name.substring(i, i + 1);
                String slc = s.toLowerCase();
                if (!s.equals(slc)) {
                    result.append("_").append(slc);
                } else {
                    result.append(s);
                }
            }

            return result.toString();
        }
    }

    /**
     * 转换为驼峰写法
     *
     * @param name
     * @return
     */
    public static String toHumpName(String name) {
        if (name == null) {
            return null;
        }
        if (name.length() <= 1) {
            return name.toLowerCase();
        }
        StringBuffer dst = new StringBuffer();
        boolean beUpCase = false;
        for (int i = 0; i < name.length(); i++) {
            String tmp = name.substring(i, i + 1);
            if ("_".equals(tmp)) {
                beUpCase = true;
                continue;
            }
            if (beUpCase) {
                dst.append(tmp.toUpperCase());
            } else {
                dst.append(tmp.toLowerCase());
            }
            beUpCase = false;
        }
        return dst.toString();

    }

    /**
     * 是windows系统
     *
     * @return
     */
    public static boolean isWindowsOS() {
        return System.getProperty("os.name").toLowerCase().indexOf("window") >= 0;
    }

    /**
     * 是linux系统
     *
     * @return
     */
    public static boolean isLinuxOS() {
        return System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0;
    }

    /**
     * 根据类型或后缀判断是否是图片
     * @param o
     * @return
     */
    public static boolean isImage(String o) {
        return "bmp,jpg,png,gif,image/png,image/jpeg".contains(o.toLowerCase());
    }


    public static Calendar calendar() {
        Calendar c = Calendar
                .getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        return c;
    }

    public static Date date() {
        return calendar().getTime();
    }

    /**
     * @return 返回字符串格式yyyy-MM-dd HH:mm:ss.SSS
     * @author majinding888@foxmail.com
     * @date 2016-8-22 下午4:08:10
     */
    public static String localDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(date());
    }

    /**
     * @return 返回字符串格式yyyyMMddHHmmssSSS
     * @author majinding888@foxmail.com
     * @date 2016-8-22 下午4:08:35
     */
    public static String localDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(date());
    }

    /**
     * @return 返回字符串格式yyyyMMddHHmmssSSS
     * @author majinding888@foxmail.com
     * @date 2016-8-22 下午4:08:35
     */
    public static String localDateTimeFmt() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date());
    }

    /**
     * @return 返回字符串格式yyyyMMddHHmmssSSS
     * @author majinding888@foxmail.com
     * @date 2016-8-22 下午4:08:35
     */
    public static String localTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        return sdf.format(date());
    }

    public static void main(String[] args) throws Exception {
        String s = "<p>测试<br/></p>";
        String r = encodeStrTo16(s);
        log.info(r);
        log.info("3C703EE6B58BE8AF953C62722F3E3C2F703E");

        String s2 = decode16ToStr(r);
        log.info(s2);

        String code = "springJdbcTemplateImpl";
        String s1 = Tools.toUnderscoreName(code);
        log.info(s1);
        s1 = Tools.toHumpName(s1);
        log.info(s1);

        log.info("{}  , {}", Tools.isWindowsOS(), Tools.isLinuxOS());
    }

}
